#include "core.h"
#include "log.h"
#include "define.h"
#include "../nlohmann/json.hpp"

Core &Core::GetInstance()
{
    static Core instance;
    return instance;
}

bool Core::Init(Config &config)
{
    // 初始化master
    std::string pubilcIp = config.m_configData.value("public_ip", "0.0.0.0");
    LOG_INFO("Public IP %s", pubilcIp.c_str());
    struct sockaddr_in addr;
    uv_ip4_addr(pubilcIp.c_str(), 0, &addr);
    g_PublicIP = addr.sin_addr.s_addr;

    if (config.m_configData.contains("master")) {
        auto &masterConfig = config.m_configData["master"];
        int spiderPort = masterConfig.value("spider_port", 0);
        int webPortStart = masterConfig.value("web_port", 0);
        int heartbeatInterval = masterConfig.value("heartbeat_interval", 0);
        int commandTimeout = masterConfig.value("command_timeout", g_CommandTimeout * 3);
        int idleTimeout = masterConfig.value("idle_timeout", g_IdleTimeout);
        if (!m_master.Init(spiderPort, webPortStart, heartbeatInterval, commandTimeout, idleTimeout))
        {
            LOG_ERROR("master Init failed");
            return false;
        }
    }
    
    // 初始化workers
    int index = 0;
    for (const auto &workerConfig : config.m_configData["workers"])
    {
        int workerType = workerConfig.value("type", 0);
        int listenPortStart = workerConfig.value("listen_port_start", 0);
        int listenPortEnd = workerConfig.value("listen_port_end", 0);
        int spiderPort = workerConfig.value("spider_port", 0);

        int commandTimeout = workerConfig.value("command_timeout", g_CommandTimeout);
        int idleTimeout = workerConfig.value("idle_timeout", g_IdleTimeout);
        m_workers.emplace_back();
        Worker &worker = m_workers.back();
        if (!worker.Init(index, workerType, listenPortStart, listenPortEnd, spiderPort, commandTimeout, idleTimeout))
        {
            LOG_ERROR("worker: %d Init failed", index);
            return false;
        }
        if (workerConfig.contains("identification"))
        {
            // 访问 identification 字段
            for (const auto &id : workerConfig["identification"])
            {
                std::string username = id.value("username", "");
                std::string password = id.value("password", "");
                if (!worker.AddIdentification(username, password))
                {
                    LOG_ERROR("worker: %d Add Identification [%s:%s] failed", index, username.c_str(), password.c_str());
                }
            }
        }

        // 访问 white_list 字段
        if (workerConfig.contains("white_list"))
        {
            for (const auto &ip : workerConfig["white_list"])
            {
                std::string whitelist_ip = ip;
                if (!worker.AddWhiteList(whitelist_ip))
                {
                    LOG_ERROR("worker: %d Add WhiteList [%s] failed", index, whitelist_ip.c_str());
                }
            }
        }

        index++;
    }
#ifdef DEBUG
    for (auto &w : m_workers)
    {
        w.ShowWorker();
    }
#endif
    return true;
}

bool Core::Start()
{
    if (!m_master.Start()) {
        LOG_ERROR("Master Start Failed");
        return false;
    }
    for (auto &worker:m_workers) {
        if (!worker.Start()) {
            LOG_ERROR("Worker: %d Start Failed", worker.GetIndex());
            return false;
        }
    }
    m_isRunning = true;
    return true;
}

void Core::Run()
{
    while(m_isRunning) {
        sleep(1);
    }
}

void Core::Stop()
{
    for (auto &worker:m_workers) {
        worker.Stop();
    }
    m_master.Stop();
    m_isRunning = false;
}
